package com.allwees.bs.task.product;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.google.common.collect.Lists;
import com.allwees.bs.module.pms.entity.Category;
import com.allwees.bs.module.pms.entity.Product;
import com.allwees.bs.module.pms.entity.Sku;
import com.allwees.bs.module.pms.service.BaseProductService;
import com.allwees.bs.module.pms.service.CategoryService;
import com.allwees.bs.module.pms.service.SkuService;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.utils.StringUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.LongAdder;

/**
 * oos图片转移至aws
 *
 * @author Daniel
 * @version 1.0.0
 * @since 2020/11/16 10:22
 */
@Component
@Slf4j
public class UploadImgToAws extends S3Processor{

    @Resource
    private SkuService skuService;

    @Resource
    private BaseProductService baseProductService;

    @Resource
    private CategoryService categoryService;

    @Resource
    private ExecutorService awsThreadPool;

    @XxlJob(value = "uploadImgToAws")
    public ReturnT<String> run(String s) throws InterruptedException {
        JSONObject json = JSON.parseObject(s);
        super.init(json);
        String module = json.getString("module");
        if ("sku".equals(module)) {
            transferSkuImg();
        } else if ("spu".equals(module)) {
            transferSpuImg();
        } else if ("cat".equals(module)) {
            transferCatImg();
        }
        return ReturnT.SUCCESS;
    }

    private void transferCatImg() {
        List<Category> categories = categoryService.list();
        for (Category category : categories) {
            if (StringUtils.contains(category.getImg(), domainName)) {
                continue;
            }
            String url = putObject("cat", "1", category.getImg(), category.getCreatedAt());
            if (StringUtils.isNotBlank(url)) {
                Category update = new Category();
                update.setId(category.getId());
                update.setImg(url);
                categoryService.updateById(update);
            }
        }
    }

    private void transferSpuImg() throws InterruptedException {
        LambdaQueryChainWrapper<Product> lambdaQuery = baseProductService
                .lambdaQuery()
                .select(Product::getId, Product::getRetailerUuid, Product::getMainPhoto, Product::getPhotosStr, Product::getCreatedAt);
        List<Product> products = lambdaQuery.list();
        if (CollectionUtils.isEmpty(products)) {
            return;
        }
        List<List<Product>> partition = Lists.partition(products, 20);
        int totalSize = products.size();
        log.info("=======================================>spu total size:{}", totalSize);
        LongAdder longAdder = new LongAdder();
        Semaphore semaphore = new Semaphore(99);
        for (List<Product> list : partition) {
            semaphore.acquire(1);
            awsThreadPool.execute(() -> {
                try {
                    int partitionSize = list.size();
                    Product update;
                    for (Product product : list) {
                        log.info("===>product id:{}", product.getId());
                        String mainPhoto = product.getMainPhoto();
                        update = new Product();
                        update.setId(product.getId());
                        boolean updated = false;
                        if (StringUtils.isNotBlank(mainPhoto) && !mainPhoto.contains(domainName)) {
                            String url = putObject("spu",product.getRetailerUuid(), mainPhoto, product.getCreatedAt());
                            if (StringUtils.isBlank(url)) {
                                log.warn(">>>>>>>>>>>>cant read spu img[mainPhoto]:{}", product.getId());
                            } else {
                                update.setMainPhoto(url);
                                updated = true;
                            }
                        }
                        String[] photoss = product.getPhotos();
                        if (photoss.length > 0) {
                            List<String> photos = new ArrayList<>();
                            for (String photo : photoss) {
                                if (photo.contains(domainName)) {
                                    photos.add(photo);
                                    continue;
                                }
                                String url = putObject("spu",product.getRetailerUuid(), photo, product.getCreatedAt());
                                if (StringUtils.isBlank(url)) {
                                    log.warn(">>>>>>>>>>>>cant read spu img[skuImg]:{}", product.getId());
                                } else {
                                    photos.add(url);
                                    updated = true;
                                }
                            }
                            update.setPhotosStr(StringUtils.join(photos, ","));
                        }

                        if (updated) {
                            baseProductService.updateById(update);
                        }
                    }
                    longAdder.add(partitionSize);
                    log.info("=======================================>spu total size:{},remain:{}", totalSize, (totalSize - longAdder.intValue()));
                } catch (Exception e) {
                    log.error(">>>>>>>>>>transferSpuImg error.", e);
                } finally {
                    semaphore.release();
                }
            });
        }
    }

    /**
     * 转移sku图片
     */
    private void transferSkuImg() {
        //1.update prod_sku s set s.`photos_str`='' where s.`photos_str` is null;
        LambdaUpdateChainWrapper<Sku> lambdaUpdate = skuService.lambdaUpdate();
        lambdaUpdate.isNull(Sku::getPhotosStr).set(Sku::getPhotosStr, "");
        lambdaUpdate.update();

        //2.select s.id,p.`retailer_uuid`,s.`photos_str` from prod_sku s left join prod_product p on s.`product_uuid`=p.`uuid` where s.`photos_str` != '';
        List<Sku> skus = skuService.queryImgs();

        List<List<Sku>> partition = Lists.partition(skus, 100);
        int totalSize = skus.size();
        log.info("=======================================>sku total size:{}", totalSize);
        LongAdder longAdder = new LongAdder();
        Semaphore semaphore = new Semaphore(100);
        for (List<Sku> list : partition) {
            semaphore.acquireUninterruptibly(1);
            awsThreadPool.execute(() -> {
                try {
                    int partitionSize = list.size();
                    longAdder.add(partitionSize);
                    for (Sku sku : list) {
                        log.info("===>sku id:{}", sku.getId());
                        String photo = sku.getPhotosStr();
                        if (photo.indexOf(domainName) > 0) {
                            continue;
                        }
                        String url = putObject("spu",sku.getUuid(), photo, sku.getCreatedAt());
                        if (StringUtils.isBlank(url)) {
                            log.warn(">>>>>>>>>>>>cant read sku img:{}", sku.getId());
                        } else {
                            skuService.lambdaUpdate().eq(Sku::getId, sku.getId()).set(Sku::getPhotosStr, url).update();
                        }
                    }
                    log.info("=======================================>sku total size:{},remain:{}", totalSize, (totalSize - longAdder.intValue()));
                } catch (Exception e) {
                    log.error(">>>>>>>>>>transferSkuImg error.", e);
                } finally {
                    semaphore.release();
                }
            });
        }
    }
}
